/**
 * @file 轨迹状态管理统一模块
 * @description 整合轨迹的元数据、播放、查询、缓存功能于一体，简化API和状态管理
 * @date 2024-08-15
 */

import { defineStore } from 'pinia'
import { getTrackData as apiGetTrackData, getTrackById as apiGetTrackById, getAllDevices } from '@/api/track'
import type { TrackData, TrackPoint, TrackQueryParams, DeviceQueryParams, DeviceListResponse } from '@/types/track'

/**
 * 缓存配置
 */
interface CacheConfig {
  /** 过期时间（毫秒） */
  ttl: number;
  /** 最大缓存项数 */
  maxSize: number;
  /** 是否自动清理 */
  autoCleanup: boolean;
}

/**
 * 轨迹缓存项
 */
interface CacheItem {
  data: TrackData;
  timestamp: number;
  expiry: number;
}

/**
 * 播放状态
 */
type PlaybackStatus = 'idle' | 'playing' | 'paused' | 'finished';

/**
 * 统一的轨迹状态管理
 */
export const useTrackStore = defineStore('track', () => {
  // ===== 状态定义 =====
  
  /**
   * 元数据状态
   */
  const metadata = {
    tracks: [] as TrackData[],
    selectedDeviceId: '',
    lastUpdated: 0,
    error: null as string | null,
    loading: false,
  };
  
  /**
   * 播放状态
   */
  const playback = {
    currentTrack: null as TrackData | null,
    currentPointIndex: 0,
    status: 'idle' as PlaybackStatus,
    speed: 1,
    timer: null as number | null,
    intervalTime: 1000, // 默认播放间隔(毫秒)
  };
  
  /**
   * 查询状态
   */
  const query = {
    params: null as TrackQueryParams | null,
    loading: false,
    error: null as string | null,
    retryCount: 0,
    maxRetries: 3,
  };
  
  /**
   * 缓存状态
   */
  const cache = {
    items: new Map<string, CacheItem>(),
    hits: 0,
    misses: 0,
    config: {
      ttl: 10 * 60 * 1000, // 10分钟
      maxSize: 50,
      autoCleanup: true,
    } as CacheConfig,
    cleanupTimer: null as number | null,
  };
  
  // ===== 计算属性 =====
  
  /**
   * 当前状态是否在加载
   */
  function getLoading() {
    return metadata.loading || query.loading;
  }
  
  /**
   * 当前错误信息
   */
  function getError() {
    return metadata.error || query.error;
  }
  
  /**
   * 当前轨迹点
   */
  function getCurrentPoint() {
    if (!playback.currentTrack || !playback.currentTrack.points) return null;
    
    const points = playback.currentTrack.points;
    if (playback.currentPointIndex >= 0 && playback.currentPointIndex < points.length) {
      return points[playback.currentPointIndex];
    }
    
    return null;
  }
  
  /**
   * 播放进度百分比
   */
  function getProgress() {
    if (!playback.currentTrack || !playback.currentTrack.points || playback.currentTrack.points.length === 0) {
      return 0;
    }
    
    return Math.min(100, Math.round((playback.currentPointIndex / (playback.currentTrack.points.length - 1)) * 100));
  }
  
  /**
   * 缓存命中率
   */
  function getCacheHitRate() {
    const total = cache.hits + cache.misses;
    return total > 0 ? Math.round((cache.hits / total) * 100) : 0;
  }
  
  /**
   * 缓存大小
   */
  function getCacheSize() {
    return cache.items.size;
  }
  
  // ===== 元数据管理方法 =====
  
  /**
   * 获取所有轨迹列表
   */
  async function getTrackList(forceRefresh = false): Promise<TrackData[]> {
    if (metadata.tracks.length > 0 && !forceRefresh) {
      return metadata.tracks;
    }
    
    metadata.loading = true;
    metadata.error = null;
    
    try {
      // 在实际项目中，这里会调用API获取轨迹列表
      // 由于示例代码中没有提供此API，使用模拟数据
      metadata.tracks = []; // 此处模拟API调用
      metadata.lastUpdated = Date.now();
      return metadata.tracks;
    } catch (err) {
      const errMsg = err instanceof Error ? err.message : '获取轨迹列表失败';
      metadata.error = errMsg;
      console.error(errMsg, err);
      return [];
    } finally {
      metadata.loading = false;
    }
  }
  
  /**
   * 通过ID获取轨迹
   */
  async function getTrackById(id: string): Promise<TrackData | null> {
    // 先查找本地缓存
    const cachedTrack = metadata.tracks.find((t: TrackData) => t.deviceId === id);
    if (cachedTrack) return cachedTrack;
    
    metadata.loading = true;
    metadata.error = null;
    
    try {
      // 调用API获取轨迹
      const response = await apiGetTrackById(id);
      
      if (response.success && response.data) {
        // 添加到本地缓存
        const track = response.data;
        if (!metadata.tracks.some((t: TrackData) => t.deviceId === track.deviceId)) {
          metadata.tracks.push(track);
        }
        return track;
      }
      
      return null;
    } catch (err) {
      const errMsg = err instanceof Error ? err.message : `获取轨迹ID: ${id}失败`;
      metadata.error = errMsg;
      console.error(errMsg, err);
      return null;
    } finally {
      metadata.loading = false;
    }
  }
  
  /**
   * 设置选中的设备ID
   */
  function setSelectedDeviceId(deviceId: string): void {
    metadata.selectedDeviceId = deviceId;
  }
  
  // ===== 轨迹播放控制方法 =====
  
  /**
   * 设置当前轨迹
   */
  function setCurrentTrack(track: TrackData | null): void {
    stopPlayback(); // 停止当前播放
    
    playback.currentTrack = track;
    playback.currentPointIndex = 0;
    playback.status = 'idle';
    
    if (track && track.points && track.points.length > 0) {
      // 通知观察者轨迹已加载
      console.log(`已加载轨迹，共${track.points.length}个点`);
    }
  }
  
  /**
   * 开始播放轨迹
   */
  function playTrack(): void {
    if (!playback.currentTrack || playback.status === 'playing') return;
    
    if (playback.status === 'finished') {
      playback.currentPointIndex = 0;
    }
    
    playback.status = 'playing';
    
    // 清除可能存在的计时器
    if (playback.timer !== null) {
      window.clearInterval(playback.timer);
    }
    
    // 设置播放计时器
    const actualInterval = playback.intervalTime / playback.speed;
    
    playback.timer = window.setInterval(() => {
      if (!playback.currentTrack || playback.status !== 'playing') {
        stopPlayback();
        return;
      }
      
      if (playback.currentPointIndex < playback.currentTrack.points.length - 1) {
        playback.currentPointIndex++;
      } else {
        // 播放结束
        playback.status = 'finished';
        stopPlayback();
      }
    }, actualInterval);
  }
  
  /**
   * 暂停播放
   */
  function pauseTrack(): void {
    if (playback.status !== 'playing') return;
    
    playback.status = 'paused';
    
    if (playback.timer !== null) {
      window.clearInterval(playback.timer);
      playback.timer = null;
    }
  }
  
  /**
   * 停止播放
   */
  function stopPlayback(): void {
    if (playback.timer !== null) {
      window.clearInterval(playback.timer);
      playback.timer = null;
    }
    
    if (playback.status === 'playing') {
      playback.status = 'paused';
    }
  }
  
  /**
   * 重置播放
   */
  function resetPlayback(): void {
    stopPlayback();
    playback.currentPointIndex = 0;
    playback.status = 'idle';
  }
  
  /**
   * 设置播放速度
   */
  function setPlaySpeed(speed: number): void {
    // 验证速度值
    if (speed <= 0) {
      console.warn('播放速度必须大于0');
      return;
    }
    
    const wasPlaying = playback.status === 'playing';
    
    // 暂停当前播放
    if (wasPlaying) {
      pauseTrack();
    }
    
    // 设置新速度
    playback.speed = speed;
    
    // 如果之前在播放，恢复播放
    if (wasPlaying) {
      playTrack();
    }
  }
  
  /**
   * 跳转到指定索引位置
   */
  function seekTo(index: number): void {
    if (!playback.currentTrack || !playback.currentTrack.points) return;
    
    const wasPlaying = playback.status === 'playing';
    
    // 暂停当前播放
    if (wasPlaying) {
      pauseTrack();
    }
    
    // 限制索引在有效范围内
    const maxIndex = playback.currentTrack.points.length - 1;
    playback.currentPointIndex = Math.max(0, Math.min(index, maxIndex));
    
    // 如果跳到最后，标记为结束
    if (playback.currentPointIndex === maxIndex) {
      playback.status = 'finished';
    } else if (playback.status === 'finished') {
      // 如果之前是完成状态，现在不是最后位置，改为暂停状态
      playback.status = 'paused';
    }
    
    // 如果之前在播放，恢复播放
    if (wasPlaying && playback.status !== 'finished') {
      playTrack();
    }
  }
  
  /**
   * 跳转到百分比位置
   */
  function seekToPercent(percent: number): void {
    if (!playback.currentTrack || !playback.currentTrack.points) return;
    
    // 限制百分比在0-100之间
    const validPercent = Math.max(0, Math.min(percent, 100));
    
    // 计算对应的索引
    const maxIndex = playback.currentTrack.points.length - 1;
    const targetIndex = Math.round((validPercent / 100) * maxIndex);
    
    // 跳转到索引
    seekTo(targetIndex);
  }
  
  // ===== 轨迹查询方法 =====
  
  /**
   * 生成缓存键
   */
  function generateCacheKey(params: TrackQueryParams): string {
    return `${params.deviceId}-${params.startTime}-${params.endTime}`;
  }
  
  /**
   * 检查缓存中是否有对应的轨迹
   */
  function hasCachedTrack(params: TrackQueryParams): boolean {
    const key = generateCacheKey(params);
    const item = cache.items.get(key);
    
    if (!item) return false;
    
    // 检查是否过期
    if (item.expiry < Date.now()) {
      cache.items.delete(key);
      return false;
    }
    
    return true;
  }
  
  /**
   * 从缓存获取轨迹
   */
  function getCachedTrack(params: TrackQueryParams): TrackData | null {
    const key = generateCacheKey(params);
    const item = cache.items.get(key);
    
    if (!item) {
      cache.misses++;
      return null;
    }
    
    // 检查是否过期
    if (item.expiry < Date.now()) {
      cache.items.delete(key);
      cache.misses++;
      return null;
    }
    
    cache.hits++;
    return item.data;
  }
  
  /**
   * 保存轨迹到缓存
   */
  function cacheTrack(params: TrackQueryParams, data: TrackData): void {
    const key = generateCacheKey(params);
    const now = Date.now();
    
    // 检查是否已达到最大缓存数
    if (cache.items.size >= cache.config.maxSize) {
      // 简单策略：删除最旧的一条记录
      let oldestKey = '';
      let oldestTime = Infinity;
      
      cache.items.forEach((item: CacheItem, itemKey: string) => {
        if (item.timestamp < oldestTime) {
          oldestTime = item.timestamp;
          oldestKey = itemKey;
        }
      });
      
      if (oldestKey) {
        cache.items.delete(oldestKey);
      }
    }
    
    // 添加到缓存
    cache.items.set(key, {
      data,
      timestamp: now,
      expiry: now + cache.config.ttl
    });
  }
  
  /**
   * 查询轨迹数据
   */
  async function getTrackData(params: TrackQueryParams, forceRefresh = false): Promise<TrackData | null> {
    query.params = params;
    query.retryCount = 0;
    
    // 检查缓存
    if (!forceRefresh) {
      const cachedData = getCachedTrack(params);
      if (cachedData) {
        console.log('使用缓存的轨迹数据');
        setCurrentTrack(cachedData);
        return cachedData;
      }
    }
    
    query.loading = true;
    query.error = null;
    
    try {
      // 调用API获取轨迹数据
      const response = await apiGetTrackData(params);
      
      if (response.success && response.data) {
        // 处理轨迹数据
        const trackData = response.data;
        
        // 缓存数据
        cacheTrack(params, trackData);
        
        // 设置为当前轨迹
        setCurrentTrack(trackData);
        
        return trackData;
      } else {
        query.error = response.message || '获取轨迹数据失败';
        return null;
      }
    } catch (err) {
      const errMsg = err instanceof Error ? err.message : '获取轨迹数据失败';
      query.error = errMsg;
      console.error(errMsg, err);
      return null;
    } finally {
      query.loading = false;
    }
  }
  
  /**
   * 重试最后一次查询
   */
  async function retryLastQuery(): Promise<TrackData | null> {
    if (!query.params || query.retryCount >= query.maxRetries) {
      console.warn('无法重试：没有上次查询或已达到最大重试次数');
      return null;
    }
    
    query.retryCount++;
    console.log(`重试获取轨迹数据 (${query.retryCount}/${query.maxRetries})`);
    
    // 强制刷新获取轨迹数据
    return await getTrackData(query.params, true);
  }
  
  /**
   * 计算轨迹距离
   */
  function calculateDistance(lat1: number, lng1: number, lat2: number, lng2: number): number {
    const radLat1 = (lat1 * Math.PI) / 180;
    const radLat2 = (lat2 * Math.PI) / 180;
    const a = radLat1 - radLat2;
    const b = (lng1 * Math.PI) / 180 - (lng2 * Math.PI) / 180;
    const s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
    const earthRadius = 6378.137; // 地球半径，单位为公里
    return s * earthRadius;
  }
  
  // ===== 缓存管理方法 =====
  
  /**
   * 清理过期缓存
   */
  function cleanupCache(): void {
    const now = Date.now();
    let expiredCount = 0;
    
    cache.items.forEach((item: CacheItem, key: string) => {
      if (item.expiry < now) {
        cache.items.delete(key);
        expiredCount++;
      }
    });
    
    if (expiredCount > 0) {
      console.log(`已清理 ${expiredCount} 条过期缓存`);
    }
  }
  
  /**
   * 开始自动清理缓存
   */
  function startCacheCleanup(): void {
    if (cache.cleanupTimer !== null || !cache.config.autoCleanup) return;
    
    // 每5分钟清理一次
    cache.cleanupTimer = window.setInterval(() => {
      cleanupCache();
    }, 5 * 60 * 1000);
    
    console.log('已启动缓存自动清理');
  }
  
  /**
   * 停止自动清理缓存
   */
  function stopCacheCleanup(): void {
    if (cache.cleanupTimer === null) return;
    
    window.clearInterval(cache.cleanupTimer);
    cache.cleanupTimer = null;
    
    console.log('已停止缓存自动清理');
  }
  
  /**
   * 清空所有缓存
   */
  function clearCache(): void {
    cache.items.clear();
    cache.hits = 0;
    cache.misses = 0;
    
    console.log('已清空所有缓存');
  }
  
  /**
   * 获取设备列表
   */
  async function getDevices(params?: DeviceQueryParams): Promise<DeviceListResponse | null> {
    metadata.loading = true;
    
    try {
      const response = await getAllDevices(params);
      
      if (response.success) {
        return response.data || null;
      }
      
      return null;
    } catch (err) {
      console.error('获取设备列表失败:', err);
      return null;
    } finally {
      metadata.loading = false;
    }
  }
  
  // ===== 生命周期钩子 =====
  
  /**
   * 初始化
   */
  function initialize(): void {
    // 启动缓存清理
    if (cache.config.autoCleanup) {
      startCacheCleanup();
    }
  }
  
  /**
   * 清理资源
   */
  function cleanup(): void {
    // 停止播放
    stopPlayback();
    
    // 停止缓存清理
    stopCacheCleanup();
  }
  
  // 启动初始化
  initialize();
  
  // 暴露给外部的状态和方法
  return {
    // 状态
    ...metadata,
    ...playback,
    
    // 计算属性
    loading: getLoading(),
    error: getError(),
    currentPoint: getCurrentPoint(),
    progress: getProgress(),
    cacheHitRate: getCacheHitRate(),
    cacheSize: getCacheSize(),
    
    // 轨迹元数据方法
    getTrackList,
    getTrackById,
    setSelectedDeviceId,
    getDevices,
    
    // 播放控制方法
    setCurrentTrack,
    playTrack,
    pauseTrack,
    resetPlayback,
    setPlaySpeed,
    seekTo,
    seekToPercent,
    
    // 查询方法
    getTrackData,
    retryLastQuery,
    
    // 缓存方法
    clearCache,
    startCacheCleanup,
    stopCacheCleanup,
    
    // 资源清理
    cleanup,
    
    // 暴露getter函数供动态使用
    getLoading,
    getError,
    getCurrentPoint,
    getProgress,
    getCacheHitRate,
    getCacheSize
  };
}); 